package pin

import (
	"fmt"
	"os"
)

// Direction Indicate whether the pin is used for input or output.
type Direction int

const (
	IN  = iota // pin is used for input
	OUT        // pin is used for output
)

// Value Indicate the current state of the pin.
type Value int

const (
	LOW  = iota // pin is low (off)
	HIGH        // pin is high (on)
)

// Pin An individual GPIO pin.
type Pin struct {
	number int
	value  *os.File
}

// OpenPin Prepare a pin for input or output.
func OpenPin(number int, direction Direction) (*Pin, error) {
	e, err := isPinExported(number)
	if err != nil {
		return nil, err
	}
	if !e {
		if err := setPinExport(number, true); err != nil {
			return nil, err
		}
	}
	if err := setPinDirection(number, direction); err != nil {
		return nil, err
	}
	var flag int
	switch direction {
	case IN:
		flag = os.O_RDONLY
	case OUT:
		flag = os.O_WRONLY
	}
	f, err := os.OpenFile(fmt.Sprintf("/sys/class/gpio/gpio%d/value", number), flag, 0)
	if err != nil {
		return nil, err
	}
	return &Pin{
		number: number,
		value:  f,
	}, nil
}
